﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Common;
using MySql.Data.MySqlClient;
using System.Data;
using SpiderContract;
using System.ServiceModel;

namespace TKWeb.Portal.SpiderConfig
{
	public partial class JobConfig : System.Web.UI.Page
	{
		private static Dictionary<int, string> s_dataType = new Dictionary<int, string>();
		static JobConfig()
		{
			s_dataType.Add(1, "字符");
			s_dataType.Add(2, "整数");
			s_dataType.Add(3, "双精度");
			s_dataType.Add(4, "日期");
			s_dataType.Add(5, "文本");
		}

		protected void Page_Load(object sender, EventArgs e)
		{
			this.CheckLogin();
			if (!this.IsPostBack)
			{
				this.JobID = "";
				this.FileID = "";
				BindJob();

				foreach(KeyValuePair<int,string> kv in s_dataType)
				{
					ddlDataType.Items.Add(new ListItem(kv.Value, kv.Key.ToString()));
				}
			}
		}

		protected string GetDataTypeName(int dataType)
		{
			string s;
			s_dataType.TryGetValue(dataType, out s);
			return s;
		}

		private void CheckLogin()
		{
			if (Global.UserId == 0)
			{
				Response.Redirect("/Passport/Login.aspx");
			}
		}

		private void BindJob()
		{
			gvJob.DataSource = GetJobs();
			gvJob.DataBind();
			SetVisible(panelGatherSettings);
		}

		private void BindFileData()
		{
			if (this.JobID == "") return;

			gvFileRule.DataSource = this.GetJobFiles(Convert.ToInt32(this.JobID));
			gvFileRule.DataBind();



			SetVisible(panelFileRule);
		}

		private void BindFieldData()
		{
			if (this.FileID == "") return;

			gvFieldRule.DataSource = this.GetFileFields(Convert.ToInt32(this.FileID));
			gvFieldRule.DataBind();
			SetVisible(panelFieldRule);
		}

		private void SetVisible(Panel pPanel)
		{
			Panel[] arrPanels = new Panel[3];
			arrPanels[0] = panelGatherSettings;
			arrPanels[1] = panelFileRule;
			arrPanels[2] = panelFieldRule;

			foreach (Panel panel in arrPanels)
			{
				if (pPanel.ID == panel.ID)
				{
					panel.Attributes.CssStyle.Add("font-size", "12px");
					panel.Visible = true;
				}
				else
				{
					panel.Visible = false;
				}
			}
		}

		protected string JobID
		{
			get { return ViewState["JobID"].ToString(); }
			set { ViewState["JobID"] = value; }
		}

		protected string FileID
		{
			get { return ViewState["FileID"].ToString(); }
			set { ViewState["FileID"] = value; }
		}


		protected void gvGatherSettings_RowUpdating(object sender, GridViewUpdateEventArgs e)
		{
			Control item = gvJob.Rows[e.RowIndex];
			CrawlJobInfo job = new CrawlJobInfo();
			job.JobId = Convert.ToInt32(gvJob.DataKeys[e.RowIndex].Value);
			job.Name = (item.FindControl("tbName") as TextBox).Text;
			job.Urls = (item.FindControl("tbUrls") as TextBox).Text;
			job.Encoding = (item.FindControl("tbEncoding") as TextBox).Text;
			job.Speed = Convert.ToInt32((item.FindControl("tbSpeed") as TextBox).Text);

			this.UpdateJob(job);
			gvJob.EditIndex = -1;
			BindJob();
		}
		protected void gvGatherSettings_RowEditing(object sender, GridViewEditEventArgs e)
		{
			gvJob.EditIndex = e.NewEditIndex;
			BindJob();
		}

		protected void gvGatherSettings_RowDeleting(object sender, GridViewDeleteEventArgs e)
		{
			this.DelJob(Convert.ToInt32(gvJob.DataKeys[e.RowIndex].Value));
			BindJob();
		}

		protected void gvGatherSettings_RowDataBound(object sender, GridViewRowEventArgs e)
		{
			if (e.Row.RowType == DataControlRowType.DataRow)
			{
				e.Row.Cells[e.Row.Cells.Count - 1].Attributes.Add("onclick", "return confirm('你确认要删除吗?');");
			}
		}
		protected void gvGatherSettings_RowCancelingEdit(object sender, GridViewCancelEditEventArgs e)
		{
			gvJob.EditIndex = -1;
			BindJob();
		}


		protected void gvGatherSettings_RowCommand(object sender, GridViewCommandEventArgs e)
		{
			switch (e.CommandName)
			{
				case "show_filerule":
					this.JobID = e.CommandArgument.ToString();
					BindFileData();
					break;
				case "StartJob":
					string[] arr = e.CommandArgument.ToString().Split(',');
					if (arr[1] == "1")
					{
						StopJob(Convert.ToInt32(arr[0]));
					}
					else
					{
						StartJob(Convert.ToInt32(arr[0]));
					}
					break;
			}
		}

		private void StartJob(int jobId)
		{
			using (ChannelFactory<ISpiderService> channelFactory = new ChannelFactory<ISpiderService>("TK.SpiderService"))
			{
				ISpiderService spider =  channelFactory.CreateChannel();
				spider.StartJob(jobId);
				BindJob();
			}
		}

		private void StopJob(int jobId)
		{
			Global.DBAccess.ExecuteNonQuery("update crawl_job set status= 0 where job_id=@job_id", new MySqlParameter("job_id", jobId));
			using (ChannelFactory<ISpiderService> channelFactory = new ChannelFactory<ISpiderService>("TK.SpiderService"))
			{
				ISpiderService spider = channelFactory.CreateChannel();
				spider.UpdateJob(jobId);
			}
			BindJob();
		}

		protected void gvFileRule_RowCommand(object sender, GridViewCommandEventArgs e)
		{
			switch (e.CommandName)
			{
				case "show_fieldrule":
					this.FileID = e.CommandArgument.ToString();
					BindFieldData();
					break;
			}
		}
		protected void gvFileRule_RowDataBound(object sender, GridViewRowEventArgs e)
		{
			if (e.Row.RowType == DataControlRowType.DataRow)
			{
				e.Row.Cells[e.Row.Cells.Count - 1].Attributes.Add("onclick", "return confirm('你确认要删除吗?');");
				if (e.Row.RowState == DataControlRowState.Edit || e.Row.RowState == (DataControlRowState.Alternate | DataControlRowState.Edit))
				{
				}
			}

			
		}


		protected void gvFileRule_RowDeleting(object sender, GridViewDeleteEventArgs e)
		{
			this.DelJobFile(Convert.ToInt32(gvFileRule.DataKeys[e.RowIndex].Value));
			BindFileData();
		}
		protected void gvFileRule_RowUpdating(object sender, GridViewUpdateEventArgs e)
		{
			Control item = gvFileRule.Rows[e.RowIndex];
			CrawlJobFileInfo fileInfo = new CrawlJobFileInfo();
			fileInfo.FileId = Convert.ToInt32(gvFileRule.DataKeys[e.RowIndex].Value);
			fileInfo.Name = (item.FindControl("tbName") as TextBox).Text;
			fileInfo.UrlPattern = (item.FindControl("tbFilePattern") as TextBox).Text;
			fileInfo.FeedRecUrl = (item.FindControl("tbFeedRecUrl") as TextBox).Text;
			fileInfo.Lua = (item.FindControl("tbLua") as TextBox).Text;
			fileInfo.JobId = Convert.ToInt32(this.JobID);
			

			this.UpdateJobFile(fileInfo);
			gvFileRule.EditIndex = -1;
			BindFileData();
		}
		protected void gvFileRule_RowEditing(object sender, GridViewEditEventArgs e)
		{
			gvFileRule.EditIndex = e.NewEditIndex;
			BindFileData();
		}

		protected void gvFileRule_RowCancelingEdit(object sender, GridViewCancelEditEventArgs e)
		{
			gvFileRule.EditIndex = -1;
			BindFileData();
		}

		protected void gvFieldRule_RowUpdating(object sender, GridViewUpdateEventArgs e)
		{
			Control item = gvFieldRule.Rows[e.RowIndex];

			CrawlJobFileFieldInfo fieldInfo = new CrawlJobFileFieldInfo();
			fieldInfo.FieldId = Convert.ToInt32(gvFieldRule.DataKeys[e.RowIndex].Value);
			fieldInfo.Name = (item.FindControl("tbName") as TextBox).Text;
			fieldInfo.Code = (item.FindControl("tbCode") as TextBox).Text;
			fieldInfo.XPath = (item.FindControl("tbXPath") as TextBox).Text;
			fieldInfo.Lua = (item.FindControl("tbLua") as TextBox).Text;
			fieldInfo.DataType = Convert.ToInt32((item.FindControl("ddlDataType") as DropDownList).SelectedValue);
			fieldInfo.DataLen = Convert.ToInt32((item.FindControl("tbDataLen") as TextBox).Text);
			fieldInfo.DataPreci = Convert.ToInt32((item.FindControl("tbDataPreci") as TextBox).Text);
			fieldInfo.FileId = Convert.ToInt32(this.FileID);
			this.UpdateFileField(fieldInfo);
			gvFieldRule.EditIndex = -1;
			BindFieldData();
		}
		protected void gvFieldRule_RowEditing(object sender, GridViewEditEventArgs e)
		{
			gvFieldRule.EditIndex = e.NewEditIndex;
			BindFieldData();

			
		}
		protected void gvFieldRule_RowDeleting(object sender, GridViewDeleteEventArgs e)
		{
			this.DelFileField(Convert.ToInt32(gvFieldRule.DataKeys[e.RowIndex].Value));
			BindFieldData();
		}

		protected void gvFieldRule_RowDataBound(object sender, GridViewRowEventArgs e)
		{
			if (e.Row.RowType == DataControlRowType.DataRow)
			{
				e.Row.Cells[e.Row.Cells.Count - 1].Attributes.Add("onclick", "return confirm('你确认要删除吗?');");

				if (e.Row.RowState == (DataControlRowState.Edit | DataControlRowState.Alternate) || e.Row.RowState == (DataControlRowState.Edit))
				{
					CrawlJobFileFieldInfo data = (CrawlJobFileFieldInfo)e.Row.DataItem;
					DropDownList ddlDataType = (DropDownList)e.Row.FindControl("ddlDataType");
					if (ddlDataType.Items.Count == 0)
					{
						foreach (KeyValuePair<int, string> kv in s_dataType)
						{
							ddlDataType.Items.Add(new ListItem(kv.Value, kv.Key.ToString()));
						}
					}

					ddlDataType.SelectedValue = data.DataType.ToString();
				}
			}
		}

		protected void gvFieldRule_RowCancelingEdit(object sender, GridViewCancelEditEventArgs e)
		{
			gvFieldRule.EditIndex = -1;
			BindFieldData();
		}

		protected void lbGotoFileRule_Click(object sender, EventArgs e)
		{
			gvFieldRule.EditIndex = -1;
			BindFileData();
		}
		protected void lbGotoSettings_Click(object sender, EventArgs e)
		{
			gvFileRule.EditIndex = -1;
			BindJob();
		}

		protected void btnAddFieldRule_Click(object sender, EventArgs e)
		{
			int dataType = 0;
			int dataLen = 0;
			int dataPreci = 0;

			CrawlJobFileFieldInfo fieldInfo = new CrawlJobFileFieldInfo();
			fieldInfo.Name = tbFieldName.Text.Trim();
			fieldInfo.Code = tbFieldCode.Text.Trim();
			fieldInfo.XPath = tbFieldXPath.Text.Trim();
			fieldInfo.Lua = tbFieldLua.Text.Trim();
			fieldInfo.FileId = Convert.ToInt32(this.FileID);
			int.TryParse(ddlDataType.SelectedValue,out dataType);
			int.TryParse(tbFieldDataLen.Text.Trim(), out dataLen);
			int.TryParse(tbFieldPreci.Text.Trim(), out dataPreci);
			fieldInfo.DataType = dataType;
			fieldInfo.DataLen = dataLen;
			fieldInfo.DataPreci = dataPreci;

			this.InsertFileField(fieldInfo);
			tbFieldName.Text = string.Empty;
			tbFieldCode.Text = string.Empty;
			tbFieldXPath.Text = string.Empty;
			tbFieldLua.Text = string.Empty;
			BindFieldData();
		}

		protected void btnAddFileRule_Click(object sender, EventArgs e)
		{
			CrawlJobFileInfo fileInfo = new CrawlJobFileInfo();
			fileInfo.JobId = Convert.ToInt32(this.JobID);
			fileInfo.Name = tbFileName.Text.Trim();
			fileInfo.UrlPattern = tbFilePattern.Text.Trim();
			fileInfo.Lua = tbFileLua.Text.Trim();
			
			this.InsertCrawlJobFile(fileInfo);

			tbFileName.Text = "";
			tbFilePattern.Text = "";
			tbFeedRecUrl.Text = "";
			tbFileLua.Text = "";
			ddIsLoad.SelectedIndex = 0;
			BindFileData();
		}
		protected void btnAddJob_Click(object sender, EventArgs e)
		{
			CrawlJobInfo jobInfo = new CrawlJobInfo();
			jobInfo.Name = tbJobName.Text.Trim();
			jobInfo.Urls = tbSeedUrls.Text.Trim();
			jobInfo.Encoding = tbEncoding.Text.Trim();
			jobInfo.Speed = Convert.ToInt32(tbSpeed.Text.Trim());
			this.InsertJob(jobInfo);
			BindJob();
		}

		public void InsertJob(CrawlJobInfo job)
		{
			string strSql = string.Format("insert into crawl_job(name,uid, seed_urls, speed,encoding,created) values(@name,@uid, @seed_urls, @speed, @encoding,sysdate())");
			Global.DBAccess.ExecuteNonQuery(strSql,
				new MySqlParameter("name", job.Name),
				new MySqlParameter("uid", Global.UserId),
				new MySqlParameter("seed_urls", job.Urls),
				new MySqlParameter("speed", job.Speed),
				new MySqlParameter("encoding", job.Encoding)
				);
		}

		private CrawlJobInfo[] GetJobs()
		{
			string strSql = @"select * from crawl_job where uid=@uid";
			using(IDataReader dr = Global.DBAccess.ExecuteReader(strSql, new MySqlParameter("uid",Global.UserId)))
			{
				return CrawlJobInfo.FillDataCollection(dr);
			}
		}

		private void UpdateJob(CrawlJobInfo job)
		{
			using (ChannelFactory<ISpiderService> channelFactory = new ChannelFactory<ISpiderService>("TK.SpiderService"))
			{
				ISpiderService spider = channelFactory.CreateChannel();
				spider.UpdateJob(job.JobId);
			}

			string strSql = @"update crawl_job set
												name=@name,
												seed_urls=@seed_urls,
												speed=@speed,
												encoding=@encoding
												where job_id=@job_id and uid=@uid";
			Global.DBAccess.ExecuteNonQuery(strSql,
				new MySqlParameter("job_id", job.JobId),
				new MySqlParameter("uid", Global.UserId),
				new MySqlParameter("name", job.Name),
				new MySqlParameter("seed_urls", job.Urls),
				new MySqlParameter("speed", job.Speed),
				new MySqlParameter("encoding", job.Encoding)
			);
		}

		public void DelJob(int jobId)
		{
			using (ChannelFactory<ISpiderService> channelFactory = new ChannelFactory<ISpiderService>("TK.SpiderService"))
			{
				ISpiderService spider = channelFactory.CreateChannel();
				spider.UpdateJob(jobId);
			}
			Global.DBAccess.ExecuteNonQuery("delete from crawl_job  where job_id=@job_id and uid=@uid", new MySqlParameter("job_id", jobId), new MySqlParameter("uid", Global.UserId));
		}

		public void InsertCrawlJobFile(CrawlJobFileInfo fileInfo)
		{
			Global.DBAccess.ExecuteNonQuery("insert into crawl_job_file(job_id,uid,name,url_pattern,fee_rec_url,lua) values(@job_id,@uid,@name,@url_pattern,@fee_rec_url,@lua)",
				new MySqlParameter("job_id", fileInfo.JobId),
				new MySqlParameter("uid", Global.UserId),
				new MySqlParameter("name", fileInfo.Name),
				new MySqlParameter("fee_rec_url", fileInfo.FeedRecUrl),
				new MySqlParameter("lua", fileInfo.Lua),
				new MySqlParameter("url_pattern", fileInfo.UrlPattern)
			);
		}


		public CrawlJobFileInfo[] GetJobFiles(int jobId)
		{
			string strSql = "select * from crawl_job_file where job_id=@job_id";
			using(IDataReader dr = Global.DBAccess.ExecuteReader(strSql, new MySqlParameter("job_id", jobId)))
			{
				return CrawlJobFileInfo.FillDataCollection(dr);
			}
		}

		public void UpdateJobFile(CrawlJobFileInfo fileInfo)
		{
			using (ChannelFactory<ISpiderService> channelFactory = new ChannelFactory<ISpiderService>("TK.SpiderService"))
			{
				ISpiderService spider = channelFactory.CreateChannel();
				spider.UpdateJob(fileInfo.JobId);
			}
			Global.DBAccess.ExecuteNonQuery("update crawl_job_file set name=@name, url_pattern=@url_pattern,fee_rec_url=@fee_rec_url,lua=@lua where file_id=@file_id and uid=@uid",
				new MySqlParameter("name", fileInfo.Name),
				new MySqlParameter("url_pattern", fileInfo.UrlPattern),
				new MySqlParameter("fee_rec_url", fileInfo.FeedRecUrl),
				new MySqlParameter("lua", fileInfo.Lua),
				new MySqlParameter("uid", Global.UserId),
				new MySqlParameter("file_id", fileInfo.FileId)
			);
		}

		public void DelJobFile(int fileId)
		{
			using (ChannelFactory<ISpiderService> channelFactory = new ChannelFactory<ISpiderService>("TK.SpiderService"))
			{
				ISpiderService spider = channelFactory.CreateChannel();
				spider.UpdateJobFile(fileId);
			}

			Global.DBAccess.ExecuteNonQuery("delete from crawl_job_file  where file_id=@file_id and uid=@uid", new MySqlParameter("file_id", fileId),new MySqlParameter("uid", Global.UserId));
		}

		public void InsertFileField(CrawlJobFileFieldInfo fieldInfo)
		{
			Global.DBAccess.ExecuteNonQuery("insert into crawl_file_field(name,file_id,uid,code,xpath,lua) values(@name,@file_id,@uid,@code,@xpath,@lua)", 
				new MySqlParameter("file_id", fieldInfo.FileId),
				new MySqlParameter("uid", Global.UserId),
				new MySqlParameter("name", fieldInfo.Name),
				new MySqlParameter("code", fieldInfo.Code),
				new MySqlParameter("xpath", fieldInfo.XPath),
				new MySqlParameter("lua", fieldInfo.Lua)
			);
		}

		public CrawlJobFileFieldInfo[] GetFileFields(int fileId)
		{
			string strSql = @"select * from crawl_file_field where file_id=@file_id";
			using (IDataReader dr = Global.DBAccess.ExecuteReader(strSql, new MySqlParameter("file_id", fileId)))
			{
				return CrawlJobFileFieldInfo.FillDataCollection(dr);
			}
		}

		public void UpdateFileField(CrawlJobFileFieldInfo fieldInfo)
		{
			using (ChannelFactory<ISpiderService> channelFactory = new ChannelFactory<ISpiderService>("TK.SpiderService"))
			{
				ISpiderService spider = channelFactory.CreateChannel();
				spider.UpdateJobFile(fieldInfo.FileId);
			}
			Global.DBAccess.ExecuteNonQuery("update crawl_file_field set name=@name,code=@code,xpath=@xpath,lua=@lua,data_type=@data_type,data_len=@data_len,data_preci=@data_preci where field_id=@field_id and uid=@uid",
				new MySqlParameter("field_id", fieldInfo.FieldId),
				new MySqlParameter("data_type", fieldInfo.DataType),
				new MySqlParameter("data_len", fieldInfo.DataLen),
				new MySqlParameter("data_preci", fieldInfo.DataPreci),
				new MySqlParameter("uid", Global.UserId),
				new MySqlParameter("name", fieldInfo.Name),
				new MySqlParameter("code", fieldInfo.Code),
				new MySqlParameter("xpath", fieldInfo.XPath),
				new MySqlParameter("lua", fieldInfo.Lua)
			);
		}

		public void DelFileField(int fileFieldId)
		{
			using (ChannelFactory<ISpiderService> channelFactory = new ChannelFactory<ISpiderService>("TK.SpiderService"))
			{
				ISpiderService spider = channelFactory.CreateChannel();
				spider.UpdateJobFile(Convert.ToInt32(this.FileID));
			}
			Global.DBAccess.ExecuteNonQuery("delete from crawl_file_field  where field_id=@field_id and uid=@uid", new MySqlParameter("field_id", fileFieldId), new MySqlParameter("uid", Global.UserId));
		}

		protected void btnTest_Click(object sender, EventArgs e)
		{
			string url = tbTestUrl.Text.Trim();
			if (string.IsNullOrEmpty(url))
			{
				return;
			}
			try
			{
				using (ChannelFactory<IAnalyzeService> channelFactory = new ChannelFactory<IAnalyzeService>("TK.AnalyzeService"))
				{
					IAnalyzeService analyze = channelFactory.CreateChannel();
					tbTestResult.Text = analyze.BuildXmlData(Convert.ToInt32(this.FileID), url);
				}
			}
			catch (Exception ex)
			{
				Response.Write(ex.ToString());
			}
		}
	}
}